﻿using System;
using System.ComponentModel;
using System.Globalization;
using System.Runtime.CompilerServices;

namespace InputKeyboard.ViewModel
{
    public class BaseWindowViewModel : INotifyPropertyChanged
    {
        #region propertyChanged
#if NETCOREAPP3_0_OR_GREATER
#nullable enable
        public event PropertyChangedEventHandler? PropertyChanged;
#nullable disable
#else
        public event PropertyChangedEventHandler PropertyChanged;
#endif
        public void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            if (!string.IsNullOrEmpty(propertyName) && PropertyChanged != null) PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion

        public BaseWindowViewModel(WindowShowParam param)
        {
            WindowParam = param;
            IsCapsLock = User32.GetCapsLockState();
            IsNumberLock = User32.GetNumberState();
            InitLanguage();
        }

        /// <summary>
        /// 窗口显示参数
        /// </summary>
        public WindowShowParam WindowParam { get; }

        #region 功能键是否按下
        private bool isCapsLock;
        /// <summary>
        /// CapsLock键是否按下了
        /// </summary>
        public bool IsCapsLock
        {
            get { return isCapsLock; }
            set { isCapsLock = value; OnPropertyChanged(); OnPropertyChanged("IsShiftOrCapsLock"); }
        }

        private bool isShift;
        /// <summary>
        /// Shift是否按下了
        /// </summary>
        public bool IsShift
        {
            get { return isShift; }
            set { isShift = value; OnPropertyChanged(); OnPropertyChanged("IsShiftOrCapsLock"); }
        }

        public bool IsShiftOrCapsLock { get { return (isCapsLock && !isShift) || (!isCapsLock && isShift); } }

        private bool isCtrl;
        /// <summary>
        /// ctrl是否按下了
        /// </summary>
        public bool IsCtrl
        {
            get { return isCtrl; }
            set { isCtrl = value; OnPropertyChanged(); }
        }

        private bool isAlt;
        /// <summary>
        /// Alt是否按下了
        /// </summary>
        public bool IsAlt
        {
            get { return isAlt; }
            set { isAlt = value; OnPropertyChanged(); }
        }

        private bool isWin;
        /// <summary>
        /// Win是否按下了
        /// </summary>
        public bool IsWin
        {
            get { return isWin; }
            set { isWin = value; OnPropertyChanged(); }
        }

        private bool isNumberLock;
        /// <summary>
        /// 数字键盘是否锁定
        /// </summary>
        public bool IsNumberLock
        {
            get { return isNumberLock; }
            set { isNumberLock = value; OnPropertyChanged(); }
        }
        #endregion

        #region 按键事件
        public virtual void KeyDown(byte key)
        {
            if (WindowParam.MultiTouch) MultiTouchKeyDown(key);
            else SingleTouchKeyDown(key);
        }

        public virtual void KeyUp(byte key)
        {
            if (WindowParam.MultiTouch) MultiTouchKeyUp(key);
            else SingleTouchKeyUp(key);
            if (key == User32.Key_NumLock) IsNumberLock = !IsNumberLock;
        }

        protected virtual void MultiTouchKeyDown(byte key)
        {
            if (key == User32.Key_CapsLock) IsCapsLock = true;
            else if (key == User32.Key_Shift) IsShift = true;
            else if (key == User32.Key_Control) IsCtrl = true;
            else if (key == User32.Key_Win) IsWin = true;
            else if (key == User32.Key_Alt) IsAlt = true;
            User32.KeyDown(key);
        }

        protected virtual void MultiTouchKeyUp(byte key)
        {
            if (key == User32.Key_CapsLock) IsCapsLock = false;
            else if (key == User32.Key_Shift) IsShift = false;
            else if (key == User32.Key_Control) IsCtrl = false;
            else if (key == User32.Key_Win) IsWin = false;
            else if (key == User32.Key_Alt) IsAlt = false;
            User32.KeyUp(key);
        }

        protected virtual void SingleTouchKeyDown(byte key)
        {
            if (key == User32.Key_Shift || key == User32.Key_Control || key == User32.Key_Win || key == User32.Key_Alt) return;
            User32.KeyDown(key);
        }

        protected virtual void SingleTouchKeyUp(byte key)
        {
            if (key == User32.Key_Shift)
            {
                if (IsShift) User32.KeyUp(key);
                else User32.KeyDown(key);
                IsShift = !IsShift;
                return;
            }
            if (key == User32.Key_Control)
            {
                if (IsCtrl) User32.KeyUp(key);
                else User32.KeyDown(key);
                IsCtrl = !IsCtrl;
                return;
            }
            if (key == User32.Key_Win)
            {
                if (IsWin) User32.KeyUp(key);
                else User32.KeyDown(key);
                IsWin = !IsWin;
                return;
            }
            if (key == User32.Key_Alt)
            {
                if (IsAlt) User32.KeyUp(key);
                else User32.KeyDown(key);
                IsAlt = !IsAlt;
                return;
            }
            User32.KeyUp(key);
            if (key == User32.Key_CapsLock) IsCapsLock = !IsCapsLock;
            if (IsWin) { User32.KeyUp(User32.Key_Win); IsWin = false; }
            if (key == User32.Key_Control || key == User32.Key_Shift || key == User32.Key_Alt) return;
            if (IsCtrl) { User32.KeyUp(User32.Key_Control); IsCtrl = false; }
            if (IsShift) { User32.KeyUp(User32.Key_Shift); IsShift = false; }
            if (IsAlt) { User32.KeyUp(User32.Key_Alt); IsAlt = false; }
        }
        #endregion

        #region 输入法
        private CultureInfo currentLanguage;
        /// <summary>
        /// 当前语言
        /// </summary>
        public CultureInfo CurrentLanguage
        {
            get { return currentLanguage; }
            protected set { currentLanguage = value; OnPropertyChanged(); }
        }

        private void InitLanguage()
        {
            if (WindowParam.Dispatcher != null)
            {
                WindowParam.Dispatcher.Invoke(() =>
                {
                    CurrentLanguage = new CultureInfo((int)User32.GetKeyboardLayout(0) & 0xFFFF);
                });
            }
        }

        public void NextLanguage()
        {
            if (WindowParam.Dispatcher != null)
            {
                WindowParam.Dispatcher?.Invoke(() =>
                {
                    var response = User32.ActivateKeyboardLayout(IntPtr.Zero, 1);
                    CurrentLanguage = new CultureInfo((int)User32.GetKeyboardLayout(0) & 0xFFFF);
                });
            }
        }

        #endregion
    }
}
